﻿/**
*
*
*这是一个用于生成自定义几何体的算法geometry.js
*Daniel
*2017.12.22
*/
define(["three"], function (THREE) {
    var geometryDraw = function (width, height, depth, widthSegments, heightSegments, depthSegments){
        THREE.Geometry.call(this);

        this.type = 'DiyGeometry';

        //设置参数默认值
        this.parameters = {
            width: width,
            height: height,
            depth: depth,
            widthSegments: widthSegments,
            heightSegments: heightSegments,
            depthSegments: depthSegments
        };

        //调用高性能几何渲染器
        this.fromBufferGeometry(new DiyBufferGeometry(width, height, depth, widthSegments, heightSegments, depthSegments));
        this.mergeVertices();
    };

    geometryDraw.prototype = Object.create(THREE.Geometry.prototype);
    geometryDraw.prototype.constructor = geometryDraw;

    function DiyBufferGeometry(width, height, depth, widthSegments, heightSegments, depthSegments){
        var scope = this;

        THREE.BufferGeometry.call(this);

        this.type = 'DiyBufferGeometry';
        this.parameters = {
            width: width,
            height: height,
            depth: depth,
            widthSegments: widthSegments,
            heightSegments: heightSegments,
            depthSegments: depthSegments
        };

        //参数默认值
        width = width || 1;
        height = height || 1;
        depth = depth || 1;

        //几何三角面参数设置
        widthSegments = Math.floor(widthSegments) || 1;
        heightSegments = Math.floor(heightSegments) || 1;
        depthSegments = Math.floor(depthSegments) || 1;

        //渲染常用参数
        var indices = [];       //索引
        var vertices = [];      //定点
        var normals = [];       //法线
        var uvs = [];           //UV贴图
        var numberOfVertices = 0;   //顶点计数器
        var groupStart = 0;         //分组

        //新建几何面
        newPlane('z', 'y', 'x', -1, -1, depth, height, width, depthSegments, heightSegments, 0); // px
        newPlane('z', 'y', 'x', 1, -1, depth, height, -width, depthSegments, heightSegments, 1); // nx
        newPlane('x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2); // py
        newPlane('x', 'z', 'y', 1, -1, width, depth, -height, widthSegments, depthSegments, 3); // ny
        newPlane('x', 'y', 'z', 1, -1, width, height, depth, widthSegments, heightSegments, 4); // pz
        newPlane('x', 'y', 'z', -1, -1, width, height, -depth, widthSegments, heightSegments, 5); // nz

        //参数API
        this.setIndex(indices);
        this.addAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));
        this.addAttribute('normal', new THREE.Float32BufferAttribute(normals, 3));
        this.addAttribute('uv', new THREE.Float32BufferAttribute(uvs, 2));

        //平面构建器
        function newPlane(u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex)
        {

            var segmentWidth = width / gridX;
            var segmentHeight = height / gridY;

            var widthHalf = width / 2;
            var heightHalf = height / 2;
            var depthHalf = depth / 2;

            var gridX1 = gridX + 1;
            var gridY1 = gridY + 1;

            var vertexCounter = 0;
            var groupCount = 0;

            var ix, iy;

            var vector = new THREE.Vector3();

            // 生成定点，法向量和UV贴图

            for (iy = 0; iy < gridY1; iy++)
            {

                var y = iy * segmentHeight - heightHalf;

                for (ix = 0; ix < gridX1; ix++)
                {

                    var x = ix * segmentWidth - widthHalf;

                    // 设置顶点构件生成
                    vector[u] = x * udir;
                    vector[v] = y * vdir;
                    vector[w] = depthHalf;

                    // 将顶点放入到顶点集合中

                    vertices.push(vector.x, vector.y, vector.z);

                    // 重置顶点构件

                    vector[u] = 0;
                    vector[v] = 0;
                    vector[w] = depth > 0 ? 1 : -1;

                    // 将重置后的顶点构件放入到法向量中

                    normals.push(vector.x, vector.y, vector.z);

                    // uvs贴图点

                    uvs.push(ix / gridX);
                    uvs.push(1 - (iy / gridY));

                    // 以上步骤完成后计数

                    vertexCounter += 1;

                }

            }

            //生成三角面

            for (iy = 0; iy < gridY; iy++)
            {
                for (ix = 0; ix < gridX; ix++)
                {
                    var a = numberOfVertices + ix + gridX1 * iy;
                    var b = numberOfVertices + ix + gridX1 * (iy + 1);
                    var c = numberOfVertices + (ix + 1) + gridX1 * (iy + 1);
                    var d = numberOfVertices + (ix + 1) + gridX1 * iy;

                    // 面数整合
                    indices.push(a, b, d);
                    indices.push(b, c, d);

                    //计数器

                    groupCount += 6;

                }

            }

            // 将生成的数据放入到Group中，方便使用材质贴图

            scope.addGroup(groupStart, groupCount, materialIndex);
            console.log(scope);

            // 重置组的数据

            groupStart += groupCount;

            // 更新顶点计数器

            numberOfVertices += vertexCounter;

        }

    }

    DiyBufferGeometry.prototype = Object.create(THREE.BufferGeometry.prototype);
    DiyBufferGeometry.prototype.constructor = DiyBufferGeometry;
    
    return geometryDraw;
    
});